package lock;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Lock和synchronized,这两个功能是最常见的锁，它们都可以达到线程安全的目的，但是在使用上和功能上又有较大的不同，Lock并不是用来代替synchronized的，而是当使用
 * synchronized不合适或不足以满足要求的时候，来提供高级功能。
 *
 * 为什么synchronized不够用？
 * 1.效率低 锁的释放情况少 （要么执行完完直接退出，要么抛异常），试图获取锁时不能设置超时、不能中断一个正在试图获得锁的线程
 * 2.不够灵活 （读写锁更灵活），读写锁可以根据读场景和写场景做出不同的动作
 * 3.无法知道是否成功获取到了锁，synchronized在获取不到锁时会一直阻塞等待
 */
@SpringBootTest(classes = MustLock.class)
public class MustLock {
    public static ReentrantLock reentrantLock = new ReentrantLock();
    /**
     * 1.lock 不会像synchronized一样 异常的时候自动释放锁
     */
    @Test
    public void test(){
        reentrantLock.lock();
        try {
            //获取本锁保护的资源
            System.out.println(Thread.currentThread().getName()+"开始执行任务");
        }finally {
            reentrantLock.unlock();
        }
    }

    /**
     * tryLock() 尝试获取锁，获取不到立即返回
     * tryLock(x,x) 尝试获取锁，获取不到尝试等待规定时间返回
     */
    @Test
    public void test2_1(){
        if (reentrantLock.tryLock()){
            try {
                //获取本锁保护的资源
                System.out.println(Thread.currentThread().getName()+"开始执行任务");
            }finally {
                reentrantLock.unlock();
            }
        }
    }

    @Test
    public void test2_2() throws InterruptedException {
        if (reentrantLock.tryLock(800, TimeUnit.MILLISECONDS)){
            try {
                //获取本锁保护的资源
                System.out.println(Thread.currentThread().getName()+"开始执行任务");
            }finally {
                reentrantLock.unlock();
            }
        }
    }

    /**
     * LockInterruptibly() 相当于tryLock（x,x）把超时时间设置为无限，在等待锁的过程中线程可以使用 Thread.Interrupter中断
     */
    @Test
    public void test3(){

    }




}
